package com.ace.token.module.service.impl;

import com.ace.token.common.constant.C;
import com.ace.token.common.constant.Redis;
import com.ace.token.common.redis.RedisValue;
import com.ace.token.common.utils.TokenUtil;
import com.ace.token.config.locale.RLocale;
import com.ace.token.exception.BusinessException;
import com.ace.token.module.entity.TokenDO;
import com.ace.token.module.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * token的service实现
 * @Author whl
 * @Date 2018年07月03日 上午8:54
 */
@Service
@Slf4j
public class TokenServiceImpl implements TokenService {

    @Autowired
    private RedisValue redisValue;

    @Autowired
    private RLocale rLocale;
    /**
     * 单个添加token,有效时间是1小时
     * @param token
     */
    @Override
    public void add(TokenDO token) {
        try {
            String userTokenKeyCache = getKey(Redis.USER_TOKEN_PREFIX,token.getUserId(),token.getType(),"*");
            Set<String> tokenCache = redisValue.selectKeys(userTokenKeyCache);
            if (!tokenCache.isEmpty()){
                redisValue.delete(userTokenKeyCache);
            }
            Date time = new Date();
            String value = TokenUtil.createToken();
            String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,token.getUserId(),token.getType(),value);
            token.setUpdateTime(time)
                 .setCreateTime(time)
                 .setValue(value);
            redisValue.add(userTokenKey,token, C.REDIS_EXPIRE_TIME);
        }catch (Exception e){
            log.debug(e.getLocalizedMessage());
            e.printStackTrace();
            throw new BusinessException(rLocale.getDTO("COMM_ERR_CREATE_TOKEN",C.T_1));
        }
    }

    /**
     * 添加token
     * @param tokens
     */
    @Override
    public void addList(List<TokenDO> tokens) {
        try {
       tokens.forEach(token->{
           Date time = new Date();
           String value = TokenUtil.createToken();
           String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,token.getUserId(),token.getType(),value);
           token.setUpdateTime(time)
                .setValue(value)
                .setCreateTime(time);
           redisValue.add(userTokenKey,token, C.REDIS_EXPIRE_TIME);
       });
       }catch (Exception e){
           log.debug(e.getLocalizedMessage());
           e.printStackTrace();
//           throw new BusinessException(R.COMM_ERR_CREATE_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_CREATE_TOKEN",C.T_1));
       }
    }
    /**
     * 根据用户id和类型删除token
     * @param token
     */
    @Override
    public void  deleteByUserIdAndType(TokenDO token){
        try{
        String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,token.getUserId(),token.getType(),"*");
        redisValue.delete(userTokenKey);
        }catch (Exception e){
            log.debug(e.getLocalizedMessage());
            e.printStackTrace();
//            throw new BusinessException(R.COMM_ERR_DELETE_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_DELETE_TOKEN",C.T_3));
        }
    }

    /**
     * 根据用户id删除token
     * @param token
     */
    @Override
    public void deleteByUserId(TokenDO token) {
        try{
            String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,token.getUserId(),"*","*");
            redisValue.delete(userTokenKey);
        }catch (Exception e){
            log.debug(e.getLocalizedMessage());
            e.printStackTrace();
//            throw new BusinessException(R.COMM_ERR_DELETE_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_DELETE_TOKEN",C.T_3));
        }
    }

    /**
     * 根据token批量删除
     * @param tokens
     */
    @Override
    public void deleteByTokenList(List<TokenDO> tokens) {
        try {
            tokens.forEach(token -> {
            	String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,"*","*",token.getValue());
                redisValue.delete(userTokenKey);
            });
        }catch (Exception e){
            log.debug(e.getLocalizedMessage());
            e.printStackTrace();
//            throw new BusinessException(R.COMM_ERR_DELETE_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_DELETE_TOKEN",C.T_3));
        }
    }

    /**
     *  根据token删除
     * @param token
     */
    @Override
    public void deleteByTokenList(TokenDO token) {
        try {
        	String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,"*","*",token.getValue());
            redisValue.delete(userTokenKey);
        }catch (Exception e){
            log.debug(e.getLocalizedMessage());
            e.printStackTrace();
//            throw new BusinessException(R.COMM_ERR_DELETE_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_DELETE_TOKEN",C.T_3));
        }
    }

    /**
     * 查询所有
     */
    @Override
    public List<TokenDO> selectAll() {
        String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,"*","*","*");
        List<TokenDO> list= redisValue.getFuzzy(userTokenKey,TokenDO.class);
       if (list == null){
           list = new ArrayList<>(1);
       }
      return list;
    }

    /**
     * 验证token
     * @param token
     */
    @Override
    public void checkToken(TokenDO token,boolean isUpdateTime) {
        String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,"*","*",token.getValue());
        List<TokenDO> resultSet = redisValue.getFuzzy(userTokenKey,TokenDO.class);
        if (resultSet == null || resultSet.isEmpty()){
//            throw new BusinessException(R.COMM_ERR_INVALD_TOKEN);
            throw new BusinessException(rLocale.getDTO("COMM_ERR_INVALID_TOKEN",C.T_0));
        }
        TokenDO tokenDO = resultSet.get(C.N_0);
        if (isUpdateTime){
            Date time = new Date();
            tokenDO.setUpdateTime(time);
            tokenDO.setCreateTime(time);
            try {
                userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,tokenDO.getUserId(),tokenDO.getType(),token.getValue());
                redisValue.add(userTokenKey,tokenDO, C.REDIS_EXPIRE_TIME);
            }catch (Exception e){
                log.debug(e.getLocalizedMessage());
                e.printStackTrace();
//                throw new BusinessException(R.COMM_ERR_UPDATE_TOKEN);
                throw new BusinessException(rLocale.getDTO("COMM_ERR_UPDATE_TOKEN",C.T_2));
            }
        }
    }

    /**
     * 创建redis中的key
     * @param values 拼接的值 (用户id.token类型.用户token)
     * @return
     */
    private String getKey(Redis prefix,String ... values){
        StringBuffer stringBuffer = new StringBuffer(prefix.getKey());
        for (String value : values) {
            stringBuffer.append(".");
            if (value !=null) {
            stringBuffer.append(value);
            }else{
                stringBuffer.append("null");
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 根据token查询用户id
     * @param token
     * @return
     */
	@Override
	public String selectByToken(TokenDO token) {
		String userTokenKey = getKey(Redis.USER_TOKEN_PREFIX,"*","*",token.getValue());
		List<TokenDO> result = redisValue.getFuzzy(userTokenKey, TokenDO.class);
		if(result == null||result.size() == 0||result.get(0) == null||result.get(0).getUserId() == null){
//			throw new BusinessException(R.TOKEN_ERR_QUERY_USER);
            throw new BusinessException(rLocale.getDTO("TOKEN_ERR_QUERY_USER", C.T_2));
		}
		return result.get(0).getUserId();
	}
}
